package com.gitee.wsl.time.sequence.sample

import com.gitee.wsl.time.atTime
import com.gitee.wsl.time.sequence.InstantSequence
import kotlin.time.Instant
import kotlinx.datetime.LocalTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import kotlin.time.Duration.Companion.days
import kotlin.time.ExperimentalTime

class EveryDayInstant(
    private val timesOfDay: List<LocalTime>,
    private val timeZone: TimeZone = TimeZone.UTC,
) : InstantSequence {

    constructor(
        timesOfDay: LocalTime,
        timeZone: TimeZone = TimeZone.UTC,
    ):this(listOf(timesOfDay),timeZone)

    @OptIn(ExperimentalTime::class)
    override fun generateSchedule(start: Instant): Sequence<Instant> {
        return sequence {
            var nextInstant = start
            while (true) {
                nextInstant = nextInstant.getNextAvailableTime()
                yield(nextInstant)
            }
        }
    }

    @OptIn(ExperimentalTime::class)
    private fun Instant.getNextAvailableTime(): Instant {
        val currentInstantAsDateTime = this.toLocalDateTime(timeZone)

        val nextAvailableTime = timesOfDay
            .firstOrNull { it > currentInstantAsDateTime.time }

        return if (nextAvailableTime != null) {
            currentInstantAsDateTime
                .atTime(nextAvailableTime)
                .toInstant(timeZone)
        } else {
            this
                .plus(1.days)
                .toLocalDateTime(timeZone)
                .atTime(timesOfDay.first())
                .toInstant(timeZone)
        }
    }


     companion object {
         /*operator fun invoke(
            vararg timesOfDay: LocalTime = arrayOf(LocalTime.fromSecondOfDay(0)),
            timeZone: TimeZone = TimeZone.UTC,
        ): EveryDayInstant {
            check(timesOfDay.isNotEmpty()) {
                "timesOfDay cannot be empty"
            }

            return EveryDayInstant(timesOfDay.sorted(), timeZone)
        }*/
    }
}

fun InstantSequence.Companion.everyDay(
    vararg timesOfDay: LocalTime = arrayOf(LocalTime.fromSecondOfDay(0)),
    timeZone: TimeZone = TimeZone.UTC,
): InstantSequence {
    check(timesOfDay.isNotEmpty()) {
        "timesOfDay cannot be empty"
    }
    return EveryDayInstant(timesOfDay.sorted(), timeZone)
}